home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / VISITYPE.ASM < prev    next >
Assembly Source File  |  1987-01-28  |  15KB  |  316 lines

  1. VECTORS SEGMENT AT 0H           ;Set up segment to intercept Interrupts
  2.         ORG     9H*4            ;The keyboard Interrupt
  3. KEYBOARD_INT     LABEL   WORD
  4.         ORG     1CH*4           ;Timer Interrupt
  5. TIMER_VECTOR      LABEL   WORD
  6. VECTORS ENDS
  7.  
  8. SCREEN  SEGMENT AT 0B000H       ;A dummy segment to use as the
  9. SCREEN  ENDS                    ;Extra Segment 
  10.  
  11. ROM_BIOS_DATA   SEGMENT AT 40H  ;BIOS statuses held here, also keyboard buffer
  12.  
  13.         ORG     1AH
  14.         HEAD DW      ?                  ;Unread chars go from Head to Tail
  15.         TAIL DW      ?
  16.         BUFFER       DW      16 DUP (?)         ;The buffer itself
  17.         BUFFER_END   LABEL   WORD
  18.  
  19. ROM_BIOS_DATA   ENDS
  20.  
  21. CODE_SEG        SEGMENT
  22.         ASSUME  CS:CODE_SEG
  23.         ORG     100H               ;ORG = 100H to make this into a .COM file
  24. FIRST:  JMP     LOAD_BUFFER        ;First time through 
  25.  
  26.         COPY_RIGHT      DB      'Copyright 1986 Ziff-Davis Publishing Co.'
  27.         BUFF            DW      0
  28.         BUFF2           DW      159 DUP(0)
  29.         PAD_OFFSET      DW      0               ;Chooses 1st 160 bytes or 2nd
  30.         SCREEN_SEG_OFFSET       DW      0       ;0 for mono, 8000H for graphics
  31.         IO_CHAR         DW      1               ;Holds addr of Put or Get_Char
  32.         OLD_HEAD        DW      1               ;To check for typeahead.
  33.         DISPLAY_ON      DB      0               ;0 --> Off.
  34.         STATUS_PORT     DW      0               ;Video controller status port
  35.         NEAR_ATTRIB_FLAG        DB      0       ;Used in Put_Char
  36.         OLD_KEYBOARD_INT_LABEL  LABEL   DWORD
  37.         OLD_KEYBOARD_INT        DW      0       ;Location of old kbd interrupt 
  38.                                 DW      0
  39.         ROM_TIMER_LABEL         LABEL   DWORD
  40.         ROM_TIMER               DW      0       ;The Timer interrupt's address
  41.                                 DW      0
  42.  
  43. BUFSTUFF PROC    NEAR            ;The keyboard interrupt will now come here.
  44.         ASSUME  CS:CODE_SEG
  45.         PUSH    AX              ;Save the used registers for good form
  46.         PUSH    BX
  47.         PUSH    CX
  48.         PUSH    DX
  49.         PUSH    DI
  50.         PUSH    SI
  51.         PUSH    DS
  52.         PUSH    ES
  53.         PUSHF                           ;First, call old keyboard interrupt
  54.         CALL    OLD_KEYBOARD_INT_LABEL
  55.         ASSUME  DS:ROM_BIOS_DATA        ;Examine the char just put in
  56.         MOV     BX,ROM_BIOS_DATA
  57.         MOV     DS,BX
  58.         MOV     BX,TAIL                 ;Point to current tail
  59.         CMP     BX,HEAD                 ;If at head, kbd int has deleted char
  60.         JNE     CONT
  61.         JMP     OUT                     ;So leave 
  62. CONT:   MOV     DX,TAIL                 ;Read a char -- head advances.
  63.         SUB     DX,2                    ;Point to just read in character
  64.         CMP     DX,OFFSET BUFFER        ;Did we undershoot buffer?
  65.         JAE     NOWRAP                  ;Nope
  66.         MOV     DX,OFFSET BUFFER_END    ;Yes -- move to buffer top
  67.         SUB     DX,2                    
  68. NOWRAP: MOV     BX,DX
  69.         MOV     CX,[BX]                 ;Get key in CX
  70.         CMP     CX,BUFF                 ;Is it where we were before?
  71.         JNE     T10
  72.         MOV     BX,HEAD                 ;Has the head moved?
  73.         CMP     BX,OLD_HEAD
  74.         JE      T11                     ;If yes, we have moved.
  75. T10:    CMP     BUFF2,0
  76.         JNE     REMOVE                  ;If there's something in BUFF2,
  77. T11:    CMP     DX,HEAD                 ; remove char in kbd buffer.
  78.         JNE     REMOVE
  79.         JMP     OUT                     ;Do nothing this pass.
  80.         ;More than one char in buffer -- Remove One!
  81. REMOVE: MOV     BX,DX
  82.         MOV     TAIL,DX                 ;Remove character by adjusting tail.
  83.         MOV     DX,[BX]                 ;Store character in buffer.
  84.         MOV     CX,80
  85.         MOV     BX,0                    ;Find end of visitype buffer.
  86. CHECK:  CMP     BUFF2[BX],0
  87.         JE      BUFEND
  88.         ADD     BX,2
  89.         LOOP    CHECK
  90.         CMP     DX,0E08H                ;Was this key a rubout?
  91.         JNE     OUT                     ;No, and buffer filled -- leave.
  92.         MOV     BX,158                  ;Yes, buff full but rubout last char.
  93.         MOV     WORD PTR BUFF[BX],0
  94.         MOV     BX,HEAD
  95.         MOV     OLD_HEAD,BX             ;Store this for next time.
  96.         MOV     DX,[BX]                 ;Always load BUFF.
  97.         MOV     BUFF,DX
  98.         JMP     OUT                     ;Can't hold more than 80!
  99. BUFEND: CMP     DX,0E08H                ;Rubout (and buffer not full)?
  100.         JNE     NODEL                   ;No, don't del.
  101. DEL:    SUB     BX,2                    ;Yes, delete last key.
  102.         CMP     BX,0FFFEH               ;Gone too far?
  103.         JL      OUT
  104.         JNE     PADDEL
  105.         MOV     CX,TAIL                 ;Del the one char in kdb buffer
  106.         MOV     HEAD,CX                 ; by making tail = head.
  107.         MOV     BUFF,0
  108.         JMP     SHORT CHKDIS
  109. PADDEL: MOV     DX,0                    ;DX --> 0 if we are deleting.
  110. NODEL:  MOV     BUFF2[BX],DX            ;Load key in Visitype buffer.
  111.         MOV     BX,HEAD
  112.         MOV     OLD_HEAD,BX             ;And store the old head to check later.
  113.         MOV     DX,[BX]                 ;Always reload BUFF.
  114.         MOV     BUFF,DX
  115. CHKDIS: CMP     DISPLAY_ON,0            ;Are we on?
  116.         JNE     FLASH                   ;Yes, call DISPLAY
  117.         MOV     DISPLAY_ON,0FFH         ;Store what's on the screen first.
  118.         MOV     PAD_OFFSET,160          
  119.         LEA     AX,GET_CHAR             ;Make IO use Get-Char so it does.
  120.         MOV     IO_CHAR,AX              
  121.         CALL    IO                      ;Get top line from screen.
  122. FLASH:  CALL    DISPLAY                 ;Display VISITYPE's top line.
  123. OUT:    POP     ES                      ;Having done Pushes, here are the Pops
  124.         POP     DS
  125.         POP     SI
  126.         POP     DI
  127.         POP     DX
  128.         POP     CX
  129.         POP     BX
  130.         POP     AX     
  131.         IRET                            ;An interrupt needs an IRET
  132. BUFSTUFF ENDP
  133.  
  134. DISPLAY PROC    NEAR                    ;Puts the whole pad on the screen
  135.         PUSH    AX
  136.         MOV     NEAR_ATTRIB_FLAG,0
  137.         MOV     PAD_OFFSET,0            ;Use 1st bytes of pad memory
  138.         LEA     AX,PUT_CHAR             ;Make IO use Put-Char so it does
  139.         MOV     IO_CHAR,AX              
  140.         CALL    IO                      ;Put result on screen
  141.         POP     AX
  142.         RET                             ;Leave
  143. DISPLAY ENDP
  144.  
  145. GET_CHAR        PROC    NEAR    ;Gets a char from screen and advances position
  146.         ASSUME  ES:SCREEN,DS:ROM_BIOS_DATA
  147.         PUSH    DX
  148.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  149.         MOV     DX,STATUS_PORT  ;Get ready to read video controller status
  150. G_WAIT_LOW:                     ;Start waiting for a new horizontal scan -
  151.         IN      AL,DX           ;Make sure the video controller scan status
  152.         TEST    AL,1            ;is low
  153.         JNZ     G_WAIT_LOW
  154. G_WAIT_HIGH:                    ;After port has gone low, it must go high
  155.         IN      AL,DX           ;before it is safe to read directly from
  156.         TEST    AL,1            ;the screen buffer in memory
  157.         JZ      G_WAIT_HIGH
  158.         MOV     AX,ES:[DI]      ;Do the move from the screen, one byte at a time
  159.         INC     DI              ;Move to next screen location                   
  160.         DEC     SI              ;Decrement loop counter
  161.         CMP     SI,0            ;Are we done?
  162.         JE      LEAVE           ;Yes
  163.         MOV     BUFF[BX],AX     ;No -- put char we got into BUFF.
  164.         JMP     G_WAIT_LOW      ;Do it again
  165. LEAVE:  ADD     BX,2
  166.         POP     DX
  167.         RET
  168. GET_CHAR        ENDP
  169.  
  170. PUT_CHAR        PROC    NEAR    ;Puts one char on screen and advances position
  171.         PUSH    DX
  172.         CLI
  173.         MOV     AH,BYTE PTR BUFF[BX]      
  174.         MOV     SI,2            ;Loop twice, once for char, once for attribute
  175.         MOV     DX,STATUS_PORT  ;Get ready to read video controller status
  176. P_WAIT_LOW:                     ;Start waiting for a new horizontal scan -
  177.         IN      AL,DX           ;Make sure the video controller scan status
  178.         TEST    AL,1            ;is low
  179.         JNZ     P_WAIT_LOW
  180. P_WAIT_HIGH:                    ;After port has gone low, it must go high
  181.         IN      AL,DX           ;before it is safe to write directly to
  182.         TEST    AL,1            ;the screen buffer in memory
  183.         JZ      P_WAIT_HIGH
  184.         MOV     ES:[DI],AH      ;Move to screen, one byte at a time
  185.         MOV     AH,BYTE PTR BUFF[BX+1]
  186.         CMP     NEAR_ATTRIB_FLAG,0
  187.         JNE     INCDI
  188.         MOV     AH,BYTE PTR BUFF[BX+161]
  189. INCDI:  INC     DI              ;Point to next screen postion
  190.         DEC     SI              ;Decrement loop counter
  191.         JNZ     P_WAIT_LOW      ;If not zero, do it one more time
  192.         ADD     BX,2
  193.         POP     DX
  194.         STI
  195.         RET                     ;Exeunt
  196. PUT_CHAR        ENDP
  197.  
  198. IO      PROC    NEAR            ;This scans over screen positions on top line.
  199.         ASSUME  ES:SCREEN       ;Use screen as extra segment
  200.         MOV     BX,SCREEN
  201.         MOV     ES,BX
  202.         MOV     DI,SCREEN_SEG_OFFSET    ;DI will be pointer to screen postion
  203.         MOV     BX,PAD_OFFSET           ;BX will be location pointer
  204.         MOV     CX,80
  205. CHAR_LOOP:
  206.         CALL    IO_CHAR                 ;Call Put-Char or Get-Char
  207.         LOOP    CHAR_LOOP               ;If not zero, scan over next character
  208.         RET                             ;Finished
  209. IO      ENDP
  210.  
  211.         ASSUME  DS:CODE_SEG
  212. INTERCEPT_TIMER   PROC    NEAR          ;This completes filling the buffer
  213.         ;IF NO KEYS IN BUFFER, PUT NEXT ONE IN.
  214.         PUSH    DS                      ;Save DS since we'll change it
  215.         PUSH    CS                      ;Put current value of CS into DS
  216.         POP     DS
  217.         PUSHF
  218.         CALL    ROM_TIMER_LABEL         ;Make obligatory call
  219.         CMP     BUFF2,0
  220.         JNE     GO                      ;No, leave
  221.         JMP     OUT1
  222. GO:     CLI                             ;Yes, start by clearing interrupts
  223.         PUSH    ES
  224.         PUSH    DS                      ;Save these.
  225.         PUSH    SI
  226.         PUSH    DI
  227.         PUSH    DX
  228.         PUSH    CX
  229.         PUSH    BX
  230.         PUSH    AX
  231.         ASSUME  DS:ROM_BIOS_DATA        ;Point to the keyboard buffer again.
  232.         MOV     AX,ROM_BIOS_DATA
  233.         MOV     DS,AX
  234.         MOV     BX,TAIL                 ;Prepare to put characters in at tail
  235.         CMP     HEAD,BX                 ;If kbd buff not empty, leave.
  236.         JNE     FINSTUFF
  237. STUFF:  MOV     AX,WORD PTR BUFF2       ;Get the char to put in kbd buffer.
  238.         MOV     CX,79                   ;Now slide the rest over.
  239.         MOV     BX,0
  240. SLIDE:  MOV     DX,BUFF[BX+2]           ;Do this word by word.
  241.         MOV     BUFF[BX],DX
  242.         ADD     BX,2
  243.         INC     SI
  244.         LOOP    SLIDE                   ;Slides slides BUFF to the left.
  245.         MOV     WORD PTR BUFF2[BX-2],0
  246.         MOV     DX,HEAD                 ;Store this to check if user is typing
  247.         MOV     OLD_HEAD,DX             ; while we drain BUFF.
  248.         MOV     DX,TAIL                 ;Find position in buffer from BX
  249.         ADD     DX,2                    ;Move to next position for this word
  250.         CMP     DX,OFFSET BUFFER_END    ;Are we past the end?
  251.         JL      NO_WRAP                 ;No, don't wrap
  252.         MOV     DX,OFFSET BUFFER        ;Do the Wrap rap.
  253. NO_WRAP:CMP     DX,HEAD                 ;Buffer full but not yet done?
  254.         JE      FINSTUFF                ;Time to leave, come back later.
  255.         MOV     BX,TAIL                 ;Prepare to put characters in at tail
  256.         MOV     [BX],AX                 ;Put into buffer
  257.         MOV     TAIL,DX                 ;Reset buffer tail
  258. FINSTUFF:CMP    BUFF2,0
  259.         JNE     DIS                     ;Should we restore the screen?
  260.         MOV     BUFF,0
  261.         MOV     DISPLAY_ON,0
  262.         MOV     PAD_OFFSET,160          ;Use 1st 160 bytes of memory
  263.         LEA     AX,PUT_CHAR             ;Make IO use Put-Char so it does
  264.         MOV     IO_CHAR,AX              
  265.         MOV     NEAR_ATTRIB_FLAG,0FFH
  266.         CALL    IO                      ;Put result on screen
  267.         JMP     SHORT ODIS
  268. DIS:    CALL   DISPLAY
  269. ODIS:   POP     AX                      ;Restore these.
  270.         POP     BX
  271.         POP     CX
  272.         POP     DX
  273.         POP     DI
  274.         POP     SI
  275.         POP     DS
  276.         POP     ES
  277. OUT1:   POP     DS
  278.         IRET                            ;With customary IRET
  279. INTERCEPT_TIMER   ENDP
  280.  
  281. LOAD_BUFFER        PROC    NEAR    ;This procedure intializes everything
  282.         ASSUME  DS:VECTORS   ;The data segment will be the Interrupt area
  283.         MOV     AX,VECTORS
  284.         MOV     DS,AX
  285.         MOV     AX,KEYBOARD_INT         ;Get the old interrupt service routine
  286.         MOV     OLD_KEYBOARD_INT,AX     ;address and put it into our location
  287.         MOV     AX,KEYBOARD_INT[2]      ;OLD_KEYBOARD_INT so we can call it.
  288.         MOV     OLD_KEYBOARD_INT[2],AX
  289.         MOV     KEYBOARD_INT,OFFSET BUFSTUFF
  290.         MOV     KEYBOARD_INT[2],CS         
  291.         MOV     AX,TIMER_VECTOR         ;Now same for timer
  292.         MOV     ROM_TIMER,AX
  293.         MOV     AX,TIMER_VECTOR[2]
  294.         MOV     ROM_TIMER[2],AX
  295.         MOV     TIMER_VECTOR,OFFSET INTERCEPT_TIMER
  296.         MOV     TIMER_VECTOR[2],CS      ;And intercept that too.
  297.         ASSUME  DS:ROM_BIOS_DATA
  298.         MOV     AX,ROM_BIOS_DATA
  299.         MOV     DS,AX
  300.         MOV     BX,OFFSET BUFFER        ;Clear the keyboard buffer to start.
  301.         MOV     HEAD,BX
  302.         MOV     OLD_HEAD,BX
  303.         MOV     TAIL,BX
  304.         MOV     AH,15                   ;Ask for service 15 of INT 10H 
  305.         INT     10H                     ;This tells us how display is set up
  306.         MOV     STATUS_PORT,03BAH       ;Assume this is a monochrome display
  307.         TEST    AL,4                    ;Is it?
  308.         JNZ     EXIT                    ;Yes - jump out
  309.         MOV     SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display
  310.         MOV     STATUS_PORT,03DAH
  311. EXIT:   MOV     DX,OFFSET LOAD_BUFFER      ;Set up everything but LOAD_BUFFER to
  312.         INT     27H                        ;stay and attach itself to DOS
  313. LOAD_BUFFER        ENDP
  314.         CODE_SEG        ENDS
  315.         END     FIRST   ;END "FIRST" so 8088 will go to FIRST first.
  316.